package javasec.contempt.installer;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;

import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

public class ContemptInstaller extends Frame
{
	private static final long serialVersionUID = 3977190589184124086L;

	private TextArea textArea;
	private JProgressBar progressBar;

	private Checkbox desktopCheck;
	private Checkbox pathCheck;
	private Checkbox menuCheck;
	
	private Button changeButton;
	private Button installButton;
	private Button cancelButton;
	
	private String osName=System.getProperty("os.name");
	private String osArch=System.getProperty("os.arch");
	private String installPath=System.getProperty("user.home")+File.separator+".contempt";
	
	public static ContemptInstaller instance=null;
	
	public static void main(String[] args)
	{
		new ContemptInstaller();
		instance.setVisible(true);
	}
	
	public ContemptInstaller()
	{
		super("contempt installer");
		instance=this;
		
		setSize(500,309);

		addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});

		textArea=new TextArea("");
		add(textArea,BorderLayout.NORTH);
		
		progressBar=new JProgressBar();
		add(progressBar, BorderLayout.CENTER);
		progressBar.setPreferredSize(new Dimension(3000,3));
		
		// add buttons and checkboxes
		Panel bottomPanel=new Panel();
		bottomPanel.setLayout(new GridLayout(3,2,1,1));
		
		desktopCheck=new Checkbox("add to desktop");
		bottomPanel.add(desktopCheck);

		changeButton = new Button("change path");
		changeButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				FileDialog dialog=new FileDialog(ContemptInstaller.instance,"select path");
				dialog.setDirectory(installPath);
				dialog.setVisible(true);
				String newPath=dialog.getDirectory();
				if(newPath==null || dialog.getFile()==null)return;
				if(new File(newPath).isDirectory())
				{
					installPath=newPath;
					textArea.append("changed install path to "+newPath+"\n");
				}
				else textArea.append("selected path was not a directory\n");
			}
		});
		bottomPanel.add(changeButton);
		
		pathCheck=new Checkbox("add to path");
		bottomPanel.add(pathCheck);

		installButton = new Button("install contempt");
		installButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				new Thread()
				{
					public void run()
					{
						install();
					}
				}.start();
			}
		});
		bottomPanel.add(installButton);

		menuCheck=new Checkbox("add to menu");
		bottomPanel.add(menuCheck);

		cancelButton = new Button("cancel");
		cancelButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});
		bottomPanel.add(cancelButton);
		
		add(bottomPanel, BorderLayout.SOUTH);
		
        textArea.setText("operating system : "+osName+"\n");
        textArea.append("architecture : "+osArch+"\n");
        textArea.append("install path : "+installPath+"\n\n");
        textArea.append("contempt is ready to install\n\n");
	}
	
	public boolean install()
	{
		// download code
		String smallOS="";
		String smallArch="";
		if(osName.contains("Lin"))smallOS="lin";
		else if(osName.contains("OSX"))smallOS="osx";
		else smallOS="win";
		if(osArch.contains("64"))smallArch="64";
		else smallArch="32";
		String urlString="http://seedsofcontempt.org/download/contempt-"+smallOS+smallArch+".zip";
		textArea.append("downloading archive\n  "+urlString+"\n\n");
		
		File archiveFile=null;
		File archiveDir=new File(installPath);
		if(!archiveDir.exists())archiveDir.mkdir();
		
		try
		{
			URL url=new URL(urlString);
			progressBar.setMaximum(url.openConnection().getContentLength());
			textArea.append("remote file is "+progressBar.getMaximum()+" bytes\n");
			BufferedInputStream iStream=new BufferedInputStream(url.openStream());
			archiveFile=new File(installPath+File.separator+"contempt.zip");
			if(archiveFile.exists())textArea.append("overwriting contempt.zip");
			FileOutputStream oStream=new FileOutputStream(archiveFile);
			byte[] buffer=new byte[1024];
			int count=0;
			int downloaded=0;
			while((count=iStream.read(buffer))!=-1)
			{
				oStream.write(buffer,0,count);
				downloaded+=count;
				
				final int value=downloaded;
				SwingUtilities.invokeLater(new Runnable()
				{
					public void run()
					{
						progressBar.setValue(value);
					}
				});
			}
			oStream.close();
			iStream.close();
		}
		catch(Exception e)
		{
			textArea.append("\nerror downloading archive\n");
			e.printStackTrace();
			return false;
		}
		
		// verify signature
		textArea.append("\npretending to verify some sort of signature\n");
		
		// extract archive
		textArea.append("extracting archive\n");
		try
		{
			ZipFile zipFile=new ZipFile(archiveFile);
			Enumeration<ZipEntry> entries;
			entries=(Enumeration<ZipEntry>)zipFile.entries();

			while(entries.hasMoreElements())
			{
				ZipEntry entry=entries.nextElement();
				String path=installPath+entry.getName();
				path=path.replaceFirst("contemptcontempt","contempt");
				//textArea.append("extracting "+path+"\n");
				
				if(entry.isDirectory())new File(path).mkdir();
				else
				{
					InputStream iStream=zipFile.getInputStream(entry);
					FileOutputStream oStream=new FileOutputStream(path);
					byte[] buffer=new byte[1024];
					int count=0;
					while((count=iStream.read(buffer))!=-1)
					{
						oStream.write(buffer,0,count);
					}
					oStream.close();
					iStream.close();
				}
			}
		}
		catch(Exception e)
		{	
			textArea.append("failed to extract the archive");
			e.printStackTrace();
		}
		
		try
		{
			if(!smallOS.equals("win"))
				Runtime.getRuntime().exec("chmod +x "+installPath+File.separator+"contempt");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		// set up shortcuts
		/*
		textArea.append("setting up requested shortcuts\n");
		try
		{
			String src=installPath+File.separator+"contempt";
			String dst=System.getProperty("user.home")+File.separator+"Desktop";
			if(smallOS.equals("win"))Runtime.getRuntime().exec("shortcut -t "+src+".exe -n "+dst+".lnk");
			else
			{
				// change permissions on the executable
				Runtime.getRuntime().exec("chmod +x "+src);
				
				// put the shortcut on the desktop
				Runtime.getRuntime().exec("ln -s "+src+" "+dst);
			}
		}
		catch(Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/
		
		textArea.append("\nContempt has been installed successfully\n");
		textArea.append("\nsorry, but no shortcuts were added, this installer is still new\n");
		textArea.append("you should be able to find the contempt binary in ~/.contempt\n");
		
		return true;
	}
}
